#include "dirent.h"
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <mh/common.h>
#include "func.h"

/*
 * Func: GetFileName
 * Para: path -- directory
 * Retu: sum of file
 * Desc: get the number of pat/dat files
 * Auth: wzwz
 * Time: 2012.02.20
 */
int GetFileName(char *path, char sc[][MH_FILE_NAME_MAX_LEN], char suffix[][MH_FILE_SUFFIX_MAX_LEN], int size)
{
    DIR *pDir = opendir(path);
    int nRet = 0;
    char scTmp[256] = {0};
    if(pDir == NULL)
    {
        return nRet;
    }
    struct dirent* ent = NULL;
    while (NULL != (ent=readdir(pDir)))
    {
        if(ent->d_type == DT_REG)
        {
            sprintf(scTmp, "%s", ent->d_name);
            int length = strlen(scTmp) + 1;

            if(length > 5)
            {
                int bCon = (scTmp[length - 2] == 'T' || scTmp[length - 2] == 't') &&
                           (scTmp[length - 3] == 'A' || scTmp[length - 3] == 'a') &&
                           (scTmp[length - 4] == 'D' || scTmp[length - 4] == 'd') &&
                           (scTmp[length - 5] == '.');
                int bCnt = (scTmp[length - 2] == 'T' || scTmp[length - 2] == 't') &&
                           (scTmp[length - 3] == 'A' || scTmp[length - 3] == 'a') &&
                           (scTmp[length - 4] == 'P' || scTmp[length - 4] == 'p') &&
                           (scTmp[length - 5] == '.');
                int booo = (scTmp[length - 2] == '0') && (scTmp[length - 3] == '0') && (scTmp[length - 4] == '0')
                           && (scTmp[length - 5] == '.');
                if(bCon || bCnt || booo)
                {
                    if(sc)
                    {
                        memcpy(sc[nRet], scTmp, length - 5);
                    }
                    if(suffix)
                    {
                        memcpy(suffix[nRet], &scTmp[length - 5], 5);
                    }
                    nRet++;
                }
            }
        }
        else if(ent->d_type == DT_DIR && memcmp(ent->d_name, "..", 3) &&
                memcmp(ent->d_name, ".", 2))
        {
            if(sc)
            {
                sprintf(sc[nRet], "%s", ent->d_name);
            }
            if(suffix)
            {
                memset(suffix[nRet], 0, 5);
            }
            nRet++;
        }
        if(size > 0 && nRet >= size)
        {
            break;
        }
    }
    closedir(pDir);
    return nRet;
}
/*
 * get file number in path
 */
int GetFileNum(char *path)
{
    return GetFileName(path, NULL, NULL, 0);
}
/*
 *
 */
int GetFileNameFromSuffix(char *path, char *suffix, char sc[][MH_FILE_NAME_MAX_LEN], int size)
{
    DIR *pDir = opendir(path);
    int nRet = 0;
    if(pDir)
    {
        struct dirent* ent = NULL;
        int suffix_len = strlen(suffix);
        while(NULL != (ent = readdir(pDir)))
        {
            if(ent->d_type == DT_REG)
            {
                int len = strlen(ent->d_name);
                if(len > suffix_len)
                {
                    char *p = &ent->d_name[len - suffix_len];
                    if(!strcmp(p, suffix))
                    {
                        if(sc)
                        {
                            memcpy(sc[nRet], ent->d_name, len - 4);
                        }
                        ++nRet;
                    }
                }
            }
            if(size > 0 && nRet >= size)
            {
                break;
            }
        }
        closedir(pDir);
    }
    return nRet;
}
/*
 * get file number for this suffix
 */
int GetFileNumFromSuffix(char *path, char *suffix)
{
    return GetFileNameFromSuffix(path, suffix, NULL, 0);
}
#if 0
/*
 * sort files by time
 */
void SortFile(char *path, char sc[][256], char sf[][5], int size)
{
    char (*p)[256] = malloc(size * 256);
    memcpy(p, sc, size * 256);
    char (*pp)[5] = malloc(size * 5);
    memcpy(pp, sf, size * 5);
    memset(sf, 0, size * 5);
    int j = 0;
    time_t *tm = malloc(size * sizeof(time_t));
    while(j < size)
    {
        char file_name[256] = {0};
        strcat(file_name, path);
        strcat(file_name, p[j]);
        strcat(file_name, pp[j]);
        struct stat buf;
        if(!stat(file_name, &buf))
        {
            tm[j] = buf.st_ctime;
        }
        else
        {
            tm[j] = 1;//失败就将时间初始化为随机数1(可以为其他值)
        }
        //DEBUG_OUT("%d, %s, %d\n", j, file_name, tm[j]);
        j++;
    }
    int i = 0, t = 0;
    while(i < size)
    {
        j = 0, t = 0;
        while(j < size)
        {
            if(tm[j] > tm[t])
            {
                t = j;
            }
            j++;
        }
        memcpy(sc[i], p[t], strlen(p[t]) + 1);
        memcpy(sf[i], pp[t], strlen(pp[t]) + 1);
        i++;
        tm[t] = 0;
    }
    free(p);
    free(pp);
    free(tm);
}
#endif
///////////////////////////////////////////////////////////////////
#define MAX_LINE_BYTE   300
int usb_find(char *out)
{
    int ret = FALSE;
#if 1
    system("mount | grep udisk > /tmp/1.txt");
    FILE *fp = fopen("/tmp/1.txt", "r");
    char sc[MAX_LINE_BYTE] = {0};
    if(fp)
    {
        if ((fgets (sc, MAX_LINE_BYTE, fp)) != NULL)
        {
            strcpy(out, "/udisk/");
            ret = 1;
        }
        fclose(fp);
    }
    remove("/tmp/1.txt");
#else
    out[0] = 0;
    strcat(out, "/media/sda1/");
    ret = TRUE;
#endif
    return ret;
}
/*
 * compare *p1 to *p2 with its name for upper order
 */
static int NameCompareForUpperOrder(const void *p1, const void *p2)
{
    int ret = strcmp(((FILE_INFO*)p1)->file_name, ((FILE_INFO*)p2)->file_name);
    if(!ret)
    {
        ret = strcmp(((FILE_INFO*)p1)->file_suffix, ((FILE_INFO*)p2)->file_suffix);
    }
    return ret;
}
/*
 * compare *p1 to *p2 with its name for down order
 */
static int NameCompareForDownOrder(const void *p1, const void *p2)
{
    int ret = strcmp(((FILE_INFO*)p1)->file_name, ((FILE_INFO*)p2)->file_name);
    if(!ret)
    {
        ret = strcmp(((FILE_INFO*)p1)->file_suffix, ((FILE_INFO*)p2)->file_suffix);
    }
    return -ret;
}
/*
 * compare *p1 to *p2 with its time for upper order
 */
static int TimeCompareForUpperOrder(const void *p1, const void *p2)
{
    int ret = 0;
    if(((FILE_INFO*)p1)->modify_time > ((FILE_INFO*)p2)->modify_time)
    {
        ret = 1;
    }
    else if(((FILE_INFO*)p1)->modify_time < ((FILE_INFO*)p2)->modify_time)
    {
        ret = -1;
    }
    return ret;
}
/*
 * compare *p1 to *p2 with its time for down order
 */
static int TimeCompareForDownOrder(const void *p1, const void *p2)
{
    int ret = 0;
    if(((FILE_INFO*)p1)->modify_time > ((FILE_INFO*)p2)->modify_time)
    {
        ret = 1;
    }
    else if(((FILE_INFO*)p1)->modify_time < ((FILE_INFO*)p2)->modify_time)
    {
        ret = -1;
    }
    return -ret;
}
/*
 * compare *p1 to *p2 with its size for upper order
 */
static int SizeCompareForUpperOrder(const void *p1, const void *p2)
{
    int ret = 0;
    if(((FILE_INFO*)p1)->size > ((FILE_INFO*)p2)->size)
    {
        ret = 1;
    }
    else if(((FILE_INFO*)p1)->size < ((FILE_INFO*)p2)->size)
    {
        ret = -1;
    }
    return ret;
}
/*
 * compare *p1 to *p2 with its size for down order
 */
static int SizeCompareForDownOrder(const void *p1, const void *p2)
{
    int ret = 0;
    if(((FILE_INFO*)p1)->size > ((FILE_INFO*)p2)->size)
    {
        ret = 1;
    }
    else if(((FILE_INFO*)p1)->size < ((FILE_INFO*)p2)->size)
    {
        ret = -1;
    }
    return -ret;
}
/*
 * sort file list
 * param type: by which to sort file list
 */
void SortFileList(FILE_INFO *p, int size, int type)
{
    switch(type)
    {
    case SORT_FILE_BY_NAME_DOWN:
        qsort(p, size, sizeof(FILE_INFO), NameCompareForDownOrder);
        break;
    case SORT_FILE_BY_NAME_UP:
        qsort(p, size, sizeof(FILE_INFO), NameCompareForUpperOrder);
        break;
    case SORT_FILE_BY_TIME_DOWN:
        qsort(p, size, sizeof(FILE_INFO), TimeCompareForDownOrder);
        break;
    case SORT_FILE_BY_TIME_UP:
        qsort(p, size, sizeof(FILE_INFO), TimeCompareForUpperOrder);
        break;
    case SORT_FILE_BY_SIZE_DOWN:
        qsort(p, size, sizeof(FILE_INFO), SizeCompareForDownOrder);
        break;
    case SORT_FILE_BY_SIZE_UP:
        qsort(p, size, sizeof(FILE_INFO), SizeCompareForUpperOrder);
        break;
    }
}
/*
 * fill file list info
 * param file_info: info list to fill
 * param file_list: all files needed
 * param size: size of file_list/file_info
 * param dir: path end width '/'
 */
void GetFileInfoList(FILE_INFO *file_info, char file_list[][MH_FILE_NAME_MAX_LEN],
    char suffix_list[][MH_FILE_SUFFIX_MAX_LEN], int size, char *dir)
{
    int i = 0;
    memset(file_info, 0, sizeof(FILE_INFO) * size);
    char *sc = calloc(1, strlen(dir) + MH_FILE_NAME_MAX_LEN + MH_FILE_SUFFIX_MAX_LEN);
    for(i = 0; i < size; ++i)
    {
        strcat(file_info[i].file_name, file_list[i]);
        strcat(file_info[i].file_suffix, suffix_list[i]);
        sc[0] = 0;
        strcat(sc, dir);
        strcat(sc, file_list[i]);
        strcat(sc, suffix_list[i]);
        struct stat buf;
        if(!stat(sc, &buf))
        {
            file_info[i].modify_time = buf.st_ctime;//嵌入式只有这个时间会改变
            file_info[i].size = buf.st_size;
            FILE *fp = fopen(sc, "r");
            if(fp)
            {
                fread(&file_info[i].width, sizeof(file_info[i].width), 1, fp);
                fread(&file_info[i].height, sizeof(file_info[i].height), 1, fp);
                fclose(fp);
            }
        }
        else
        {
            printf("failed to stat file: %s\n", sc);
        }
    }
    free(sc);
}
/*
 * delete file out from list pointed by p
 * this only delete data not free mem(rude data linked to the tail of list)
 * param p: list pointer
 * param size: size of list
 * param index: 0-start
 * param num: how many to delete
 * return: size after delete
 */
int DeleteFileFromList(FILE_INFO *p, ushort size, int index, int num)
{
    int ret = 0;
    if(num >= size - index)
    {
        memset(&p[index], 0, sizeof(FILE_INFO) * (size - index));
        ret = index;
    }
    else
    {
        memcpy(&p[index], &p[index + num], sizeof(FILE_INFO) * (size - index - num));
        ret = size - num;
    }
    return ret;
}
/*
 * get size of dir
 */
uint GetDirSize(const char *path)
{
    DIR *pDir = opendir(path);
    long int size = 0;
    if(pDir)
    {
        struct dirent* ent = NULL;
        while (NULL != (ent=readdir(pDir)))
        {
            if(ent->d_type == DT_REG)
            {
                struct stat buf;
                char sc[1024] = {0};
                strcat(sc, path);
                strcat(sc, ent->d_name);
                if(!stat(sc, &buf))
                {
                    size += buf.st_size;
                    //printf("%s: %ld, %ld\n", ent->d_name, buf.st_size, size);
                }
            }
        }
        closedir(pDir);
    }
    return size / 1024;
}
/*
 * get all decode file for suffix is ".txt" or dir.
 * if size is 0(sc, suffix = null), only compute the size
 */
int GetDecodeFileFromDisk(const char *path, char sc[][MH_FILE_NAME_MAX_LEN],
        char suffix[][MH_FILE_SUFFIX_MAX_LEN], int size)
{
    int ret = 0;
    DIR *pDir = opendir(path);
    if(pDir)
    {
        struct dirent* ent = NULL;
        while (NULL != (ent=readdir(pDir)))
        {
            if(ent->d_type == DT_REG)
            {
                int len = strlen(ent->d_name);
                if(len > 4)
                {
                    if(!memcmp(&ent->d_name[len - 4], ".txt", 4))
                    {
                        if(sc)
                        {
                            strcat(sc[ret], ent->d_name);
                            sc[ret][len - 4] = 0;
                        }
                        if(suffix)
                        {
                            strcat(suffix[ret], &ent->d_name[len - 4]);
                        }
                        ++ret;
                    }
                }
            }
            else if(ent->d_type == DT_DIR && memcmp(ent->d_name, "..", 3) &&
                    memcmp(ent->d_name, ".", 2))
            {
                if(sc)
                {
                    strcat(sc[ret], ent->d_name);
                }
                if(suffix)
                {
                    memset(suffix[ret], 0, MH_FILE_SUFFIX_MAX_LEN);
                }
                ++ret;
            }
            if(size > 0 && ret >= size)
            {
                break;
            }
        }
        closedir(pDir);
    }
    return ret;
}
/*
 * get all update file for suffix is ".mh" or dir.
 * if size is 0(sc, suffix = null), only compute the size
 */
int GetUpdateFileFromDisk(const char *path, char sc[][MH_FILE_NAME_MAX_LEN],
        char suffix[][MH_FILE_SUFFIX_MAX_LEN], int size)
{
    int ret = 0;
    DIR *pDir = opendir(path);
    if(pDir)
    {
        struct dirent* ent = NULL;
        while (NULL != (ent=readdir(pDir)))
        {
            if(ent->d_type == DT_REG)
            {
                int len = strlen(ent->d_name);
                if(len > 3)
                {
                    if(!memcmp(&ent->d_name[len - 3], ".mh", 3))
                    {
                        if(sc)
                        {
                            strcat(sc[ret], ent->d_name);
                            sc[ret][len - 3] = 0;
                        }
                        if(suffix)
                        {
                            strcat(suffix[ret], &ent->d_name[len - 3]);
                        }
                        ++ret;
                    }
                }
            }
            else if(ent->d_type == DT_DIR && memcmp(ent->d_name, "..", 3) &&
                    memcmp(ent->d_name, ".", 2))
            {
                if(sc)
                {
                    strcat(sc[ret], ent->d_name);
                }
                if(suffix)
                {
                    memset(suffix[ret], 0, MH_FILE_SUFFIX_MAX_LEN);
                }
                ++ret;
            }
            if(size > 0 && ret >= size)
            {
                break;
            }
        }
        closedir(pDir);
    }
    return ret;
}
/*
 *
 */
void GetLinuxVersion(char *sc)
{
    int i = 0;
    char ver[256];
    int fd = open("/proc/version", 0);
    int size = 0;
    int index = 0;
    if (fd > -1)
    {
        size = read(fd, ver, 255);
        ver[size] = 0;
        for(i = 0; i < size; i++)
        {
            if(ver[i] == ':')
            {
                memcpy(sc, &ver[i + 11], 4);
                strcat(sc, "-");
                if(ver[i - 9] == ' ')
                {
                    index = i - 8;
                }
                else
                {
                    index = i - 9;
                }

                memcpy(&sc[5], &ver[index], 3);
                strcat(sc, "-");
                memcpy(&sc[9], &ver[index + 4], 2);
                break;
            }
        }
        close(fd);
    }
}
/*
 * brief: 检测模块格式
 * param: phead -- 格式头
 * return: 0=succ, <0=error num
 * date: 2015\05\26
 * author: haoyaoyao
 */
int AuxConCheck(SP_HEAD *phead)
{
    //printf("signature = %x\n", phead->signature);
    if(phead->signature != 0x66AA)
    {
        return -1;
    }

    //printf("total_rows = %d\n", phead->total_rows);
    if(phead->total_rows <= 0)
    {
        return -2;
    }

    return 0;
}
